home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / c_lib.arc / PCSETISR.C < prev    next >
Text File  |  1990-08-09  |  6KB  |  151 lines

  1. /**
  2. *
  3. *  Name         pcsetisr -- Set interrupt service routine
  4. *
  5. *  Synopsis     ercode = pcsetisr(intype,pfunc,stksize,pvector,pisrblk);
  6. *               int ercode        Error return code
  7. *               int intype        Interrupt type number
  8. *               unsigned (*pfunc)()  Pointer to interrupt service routine
  9. *               int stksize       Stack size needed for ISR
  10. *               ADS *pvector      Previous interrupt vector for the
  11. *                                 specified interrupt type.
  12. *               ISRCTRL **pisrblk Pointer to ISR control block
  13. *
  14. *  Description  pcsetisr sets the interrupt vector to point to an ISR
  15. *               control block.  The control block is used by the ISR dis-
  16. *               patcher function to set up the ISR stack, call the actual
  17. *               ISR function and handle the interrupt protocol.  The
  18. *               address of the control block is placed in the interrupt
  19. *               vector; the first bytes of the control block have the code
  20. *               necessary to invoke the ISR dispatcher.  The control block
  21. *               is a structure, space for which is allocated on the heap,
  22. *               defined as follows:
  23. *
  24. *               call instruction:  The far call instruction starts with
  25. *                    the opcode of 9A then the IP and CS values for the
  26. *                    ISR dispatcher.
  27. *               ISR stack segment and pointer: The stack segment is set by
  28. *                    PCISRSTK, and placed in variable external to PCSETISR.
  29. *                    The stack pointer is the requested size of the stack.
  30. *               Data segment value of program setting up the ISR.  The ISR
  31. *                    will use the same data segment.
  32. *               Space to store the invoking programs stack segment and
  33. *                    stack pointer.  Because the ISR dispatcher must alter
  34. *                    the stack, it must be restored before the interrupt
  35. *                    service returns.
  36. *               Pointer to the C function which processes the interrupt,
  37. *                    that is the Interrupt Service Routine (ISR).
  38. *
  39. *               The original interrupt vector is returned so that it
  40. *               may be restored if the ISR is to be disabled, and a
  41. *               pointer to the control block is returned so space can be
  42. *               freed when it is no longer needed.
  43. *
  44. *  Returns      ercode            The return code is 0 if the vector is
  45. *                                 is successfully set; other values are:
  46. *                                 1 - Interrupt type out of range
  47. *                                 2 - Cannot allocate space for ISR control
  48. *
  49. *  Version      1.1  (C)Copyright Blaise Computing Inc.  1983, 1984
  50. *
  51. **/
  52. #include <compiler.h>
  53.  
  54. #if LDATA
  55. #define NULL  0L
  56. #else
  57. #define NULL  0
  58. #endif
  59.  
  60. #define utoutrng(a,l,h) (((a)<(l)||(a)>(h))?1:0) /* Is a out of range? */
  61.  
  62. struct segads                          /* Offset, segment address type */
  63. {
  64.   unsigned r;
  65.   unsigned s;
  66. };
  67. #define ADS     struct segads          /* Abbreviation                 */
  68.  
  69. struct isr_control
  70. {
  71.   unsigned fcall_opcode;               /* Far call op code 9A          */
  72. #if LPROG
  73.   int      (*isrdisp)();               /* Pointer to ISR dispatcher    */
  74. #else
  75.   int      (*isrdisp)();
  76.   unsigned isrdisp_cs;                 /* Code segment when it is NEAR */
  77. #endif
  78.   unsigned isrss;                      /* ISR stack segment            */
  79.   unsigned isrsp;                      /* ISR stack pointer            */
  80.   unsigned isrstksize;                 /* ISR stack size               */
  81.   unsigned isrds;                      /* ISR data segment             */
  82.   unsigned savess;                     /* Location to save SS and SP   */
  83.   unsigned savesp;                     /* from invoking program        */
  84.   unsigned (*isr)();                   /* Pointer to ISR.  Note that   */
  85. };                                     /* 2 or 4 bytes depending on the*/
  86.                                        /* memory model used.           */
  87. #define ISRCTRL struct isr_control
  88.  
  89. extern unsigned isrss;                 /* ISR stack information from   */
  90. extern unsigned isrstk_base;           /* PCSISRSTK.                   */
  91.  
  92. int pcsetisr(intype,pfunc,stksize,pvector,pisrblk)
  93. int      intype,stksize;
  94. unsigned (*pfunc)();
  95. ADS      *pvector;
  96. ISRCTRL  **pisrblk;
  97. {
  98.  
  99.     ADS      isrblk_ads;
  100.     char     *calloc();
  101.     extern   int invisr();              /* ISR dispatcher               */
  102.     unsigned cs,ss,ds,es;
  103. #if CI201A & LDATA
  104.     unsigned long ptrtoabs();
  105. #endif
  106.  
  107.     if (utoutrng(intype,0,255))
  108.        return(1);
  109.  
  110.     pcretvec(intype,pvector);          /* Return the interrupt vector  */
  111.  
  112.     *pisrblk = (ISRCTRL *)calloc(1,sizeof(ISRCTRL));
  113.     if (*pisrblk == NULL)
  114.        return(2);
  115.     utsreg(&cs,&ss,&ds,&es);
  116.  
  117.     (*pisrblk)->fcall_opcode = 0x9a00;
  118. #if LPROG
  119.     (*pisrblk)->isrdisp      = invisr;  /* ISR dispatcher address        */
  120. #else
  121.     (*pisrblk)->isrdisp      = invisr;
  122.     (*pisrblk)->isrdisp_cs   = cs;
  123. #endif
  124.     (*pisrblk)->isrss        = isrss;   /* ISR stack segment and pointer */
  125.     (*pisrblk)->isrsp        = isrstk_base + 2;
  126.     (*pisrblk)->isrstksize   = stksize;
  127.     (*pisrblk)->isrds        = ds;      /* ISR data segment              */
  128.     (*pisrblk)->isr          = pfunc;   /* Interrupt service routine     */
  129.  
  130.     /* Now load the interrupt vector with the segment and offset       */
  131.     /* address of the ISR control block.                               */
  132.  
  133. #if LDATA
  134. #if CI201A
  135.     isrblk_ads.s = (unsigned)((ptrtoabs(*pisrblk) & 0xffff0L) >> 4L);
  136.     isrblk_ads.r = (unsigned)(ptrtoabs(*pisrblk) & 0xfL);
  137. #else
  138.     isrblk_ads.s = (unsigned)(((long)(*pisrblk) & 0xffff0L) >> 4L);
  139.     isrblk_ads.r = (unsigned)((long)(*pisrblk) & 0xfL);
  140. #endif
  141. #else
  142.     isrblk_ads.s = ds;
  143.     isrblk_ads.r = *pisrblk;
  144. #endif
  145.     isrblk_ads.r++;
  146.     pcsetvec(intype,&isrblk_ads);
  147.  
  148.     return(0);
  149.  
  150. }
  151.